package com.iias.communication.codec.string;

import com.alibaba.fastjson.JSON;
import com.iias.common.util.date.DateUtils;
import com.iias.common.util.log.LogUtils;
import com.iias.common.util.seq.SeqUtils;
import com.iias.communication.codec.AbstractCodec;
import com.iias.communication.domain.DecodeInfo;
import com.iias.communication.enums.Protocol;
import com.iias.communication.exception.DecodeInfoMsgNotFoundException;
import com.iias.communication.packet.PacketBody;
import com.iias.communication.packet.PacketHeard;
import com.iias.communication.packet.PacketStringBody;
import com.iias.communication.packet.ProPacket;
import com.iias.communication.util.ByteUtils;
import com.iias.communication.util.IntegerToByte;
import org.slf4j.Logger;

import java.util.*;

/**
 *
 * 普通字符串解码
 */
public class StringCodec extends AbstractCodec {

    private final static Logger log = LogUtils.getLogger();

//    private final static Map<Integer, PacketBody> DECODE_MAP = new LinkedHashMap<Integer, PacketBody>();



//    public static void addDecode(Integer msgId,BodyDecode bodyDecode){
//        DECODE_MAP.put(msgId,bodyDecode);
//        log.info(" StringCodec load msgId:  {msgId} parsingBody;" +
//                " class :  " + bodyDecode.getClass());
//    }

    private final static Map<Integer,Class<? extends PacketStringBody>> CLASS_MAP = new LinkedHashMap<Integer, Class<? extends PacketStringBody>>();


    public  boolean addPacketBody(int msgId,Class<? extends PacketBody> aClass) {
        if (PacketStringBody.class.isAssignableFrom(aClass)){
            CLASS_MAP.put(msgId, (Class<? extends PacketStringBody>) aClass);
            log.info(" StringCodec : msgId 添加成功 " + msgId);
            return true;
        }else {
            log.info( "StringCodec : msgId 添加失败 " + aClass.getClass() +" 不属于字符串解码器类型");
            return false;
        }
    }

    @Override
    public byte[] encoding(int msgId, PacketBody packetBody) {
        byte[] encoding = packetBody.encoding();
        if (encoding == null)encoding = JSON.toJSONString(packetBody).getBytes();
        String time = DateUtils.format(new Date(), DateUtils.FORMAT17_);
        byte[] seqIdByte = IntegerToByte.integerTo4Bytes(SeqUtils.getSeq());
        byte[] msgIdByte = IntegerToByte.integerTo4Bytes(msgId);
        byte[] timeByte = time.getBytes();
        byte[] versionByte = IntegerToByte.integerTo4Bytes(Protocol.COMMON_STRING.getVersion());
        byte[] lengthByte = IntegerToByte.integerTo4Bytes(encoding.length);
        byte[] heard = ByteUtils.concat(seqIdByte, msgIdByte, timeByte, versionByte, lengthByte);
        byte[] replace = replace(ByteUtils.concat(heard, encoding), HEARD_FLAG, HEARD_REPLACE);
        return ByteUtils.concat(HEARD_FLAG, replace);
    }

    private final static byte[] HEARD_FLAG = "$".getBytes();

    private final static byte[] HEARD_REPLACE  = "!-!".getBytes();



    @Override
    public DecodeInfo decodeInfo(byte[] in) {
        if (in.length<=0)return null;
        //解析头
        in = replace(in,HEARD_REPLACE,HEARD_FLAG);

        List<Integer> startIndex = ByteUtils.getStartIndex(in, HEARD_FLAG);
        int start = startIndex.get(0);
        int end = start+1;
        List<ProPacket> proPackets = new ArrayList<ProPacket>();
        for (Integer index : startIndex) {
            if (index>= in.length)continue;
            PacketHeard packetHeard = new PacketHeard();
//            序列ID 4 个长度
            int seq = IntegerToByte.byteToInteger(ByteUtils.subBytes(in, end, 4));
            end = end+4;
            packetHeard.setSeqId(seq);
//            业务ID 4个长度
            int msgId  = IntegerToByte.byteToInteger(ByteUtils.subBytes(in,end,4));
            end = end+4;
            packetHeard.setMsgId(msgId);
//            时间 8个长度
            Long  time  = Long.valueOf(new String(ByteUtils.subBytes(in,end,17)));
            end = end+17;
            packetHeard.setTime(time);
//            版本号 4个长度
            int  v  = IntegerToByte.byteToInteger(ByteUtils.subBytes(in,end,4));
            end = end+4;
            packetHeard.setVersion(v);
//            包体长度 8个长度
            int  l  = IntegerToByte.byteToInteger(ByteUtils.subBytes(in,end,4));
            end = end+4;
            packetHeard.setLength(l);
            byte[] bytes = ByteUtils.subBytes(in, end, l);
            end =end +l;

            Class<? extends PacketStringBody> aClass = CLASS_MAP.get(msgId);
            if (aClass == null){
                new DecodeInfoMsgNotFoundException(" not found msgId decode :" + msgId);
            }
            ProPacket proPacket = new ProPacket();
            proPacket.setHeard(packetHeard);
            PacketStringBody packetStringBody = JSON.parseObject(new String(bytes), aClass);
            packetStringBody.decode(bytes);
            proPacket.setPacketBody(packetStringBody);
            proPackets.add(proPacket);
        }
        return new DecodeInfo(start,end,proPackets);
    }



    public byte[] replace(byte[] in,byte[] old,byte[] newD){
        List<Integer> startIndexList = ByteUtils.getStartIndex(in, old);

        for (Integer startIndex : startIndexList) {
           in = ByteUtils.replace(in,startIndex,old,newD);
        }
        return in;
    }


}
